package cz.mff.cuni.dpp.liboptions;

import org.junit.Test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cz.mff.cuni.dpp.liboptions.OptionCallback;
import cz.mff.cuni.dpp.liboptions.Options;
import cz.mff.cuni.dpp.liboptions.Result;
import cz.mff.cuni.dpp.liboptions.StringOption;
import cz.mff.cuni.dpp.liboptions.SwitchOption;

/**
 * Ukázka použití knihovny jkaobz pro UNIX utilitu <code>Time</code>
 * 
 */
public class TimeTest {
	private static final Logger logger = LoggerFactory.getLogger(TimeTest.class);

	public static void main(String[] args) {

		// reakce na volby definovany pomoci callbacku
		OptionCallback<String> formatterCallback = new OptionCallbackAdapter<String>() {
			@Override
			public void handleOptionValue(String parameter) {
				logger.info("format: {}", parameter);
			}
		};

		OptionCallback<String> outputCallback = new OptionCallback<String>() {

			@Override
			public void handleOptionValue(String parameter) {
				logger.info("output file: {}", parameter);
			}

			@Override
			public void handleNotPresent() {
				logger.info("output file is missing, printing to standard output");
			}
		};

		OptionCallback<Boolean> portabilityCallback = new OptionCallback<Boolean>() {
			@Override
			public void handleOptionValue(Boolean parameter) {
				logger.info("portability is on");
			}

			@Override
			public void handleNotPresent() {
				logger.info("portability is off");
			}
		};

		OptionCallback<Boolean> appendCallback = new OptionCallback<Boolean>() {
			@Override
			public void handleOptionValue(Boolean parameter) {
				logger.info("append is on");
			}

			@Override
			public void handleNotPresent() {
				logger.info("append is off");
			}
		};

		OptionCallback<Boolean> verboseCallback = new OptionCallback<Boolean>() {
			@Override
			public void handleOptionValue(Boolean parameter) {
				logger.info("verbose is on");
			}

			@Override
			public void handleNotPresent() {
				logger.info("verbose is off");
			}
		};

		class HelpCallback extends OptionCallbackAdapter<Boolean> {
			private Options options;
			private String initString;

			public HelpCallback(Options options, String initString) {
				this.options = options;
				this.initString = initString;
			}

			@Override
			public void handleOptionValue(Boolean value) {
				options.printHelp(initString);
			}
		}

		// class VersionCallback implements OptionCallback<Boolean> {
		class VersionCallback extends OptionCallbackAdapter<Boolean> {
			@Override
			public void handleOptionValue(Boolean parameter) {
				logger.info("version: 1.2.3-alpha0");
			}

			@Override
			public void handleNotPresent() {
			}
		}

		// vlastni definice optionu
		Options options = new Options();

		StringOption formatterOption = new StringOption.Builder("format", "FORMAT")
				.addAlias("f")
				.setDescription(
						"Specify output format, possibly overriding the format specified in the environment variable TIME.")
				.setCallback(formatterCallback).buildOption();

		StringOption outputOption = new StringOption.Builder("output", "FILE")
				.addAlias("o")
				.setDescription(
						"Do not send the results to stderr, but overwrite the specified file.")
				.setCallback(outputCallback).buildOption();

		SwitchOption portabilityOption = new SwitchOption.Builder("portability").addAlias("p")
				.setCallback(portabilityCallback).setDescription("Use the portable output format.")
				.buildOption();

		SwitchOption appendOption = new SwitchOption.Builder("append").addAlias("a")
				.setDescription("(Used together with -o.) Do not overwrite but append.")
				.setCallback(appendCallback).buildOption();

		SwitchOption verboseOption = new SwitchOption.Builder("verbose").addAlias("v")
				.setDescription("Give very verbose output about all the program knows about.")
				.setCallback(verboseCallback).buildOption();

		SwitchOption helpOption = new SwitchOption.Builder("help")
				.setDescription("Print a usage message on standard output and exit successfully.")
				.setCallback(new HelpCallback(options, "time [options] command [arguments...]"))
				.buildOption();

		SwitchOption versionOption = new SwitchOption.Builder("version")
				.addAlias("V")
				.setDescription(
						"Print version information on standard output, then exit successfully.")
				.setCallback(new VersionCallback()).buildOption();

		options.addOptionDefinition(formatterOption);
		options.addOptionDefinition(outputOption);
		options.addOptionDefinition(portabilityOption);
		options.addOptionDefinition(appendOption);
		options.addOptionDefinition(verboseOption);
		options.addOptionDefinition(helpOption);
		options.addOptionDefinition(versionOption);

		Result result = options.process(args);

		if (result.hasErrors()) {
			options.printHelp();
		} else {
			result.callCallbacks(true);
		}
	}

	@Test
	public void timeTest() {
		TimeTest.main(new String[] { "-V" });
		// TimeTest.main(new String[] { "--help"});
		TimeTest.main(new String[] { "-f", "real %e user %U...", "--output=time.out", "-a", "-p" });
	}
}
